"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketClient = void 0;
const Logger_1 = require("../utils/Logger");
const SocketRequestData_1 = require("./SocketRequestData");
const SocketClientReqManager_1 = require("./SocketClientReqManager");
const WebSocketClientManager_1 = require("./WebSocketClientManager");
const ws = require("ws");
class WebSocketClient {
    constructor() {
        this.requestMsgQue = [];
        this.reqId = 1;
        this.respCheckMap = new Map();
    }
    init(url, id) {
        try {
            if (!this.isConnected && !this.isConnecting) {
                this.isConnecting = true;
                this.url = url;
                this.id = id;
                this.ws = new ws(url);
                Logger_1.Logger.log("WebSocketClient===init=", url, this.id);
                this.ws.on('open', () => {
                    WebSocketClient.count++;
                    this.isConnecting = false;
                    Logger_1.Logger.info("ws onConnect===", this.url, this.id, WebSocketClient.count);
                    this.isConnected = true;
                    this.checkSendPack();
                });
                this.ws.on('message', (socketData) => {
                    this.onGameMsg(socketData);
                });
                this.ws.on("error", (err) => {
                    this.isConnected = false;
                    this.isConnecting = false;
                    Logger_1.Logger.error("WebSocketClient error=====", this.id, err);
                });
                this.ws.on('close', () => {
                    this.isConnected = false;
                    this.isConnecting = false;
                    Logger_1.Logger.info('disconnected', this.id, this.url);
                    this.destroy();
                });
            }
        }
        catch (error) {
            Logger_1.Logger.error("WebSocketClient error=", error);
        }
    }
    onGameMsg(socketData) {
        try {
            let obj = JSON.parse(socketData);
            let id = obj["id"];
            let socketReqData = this.respCheckMap.get(id);
            if (socketReqData) {
                this.respCheckMap.delete(id);
                if (socketReqData.callback) {
                    socketReqData.callback(obj["data"]);
                }
                else {
                    SocketClientReqManager_1.SocketClientReqManager.instance.onSocketMsg(obj["protoName"], obj["data"]);
                }
            }
            else {
                SocketClientReqManager_1.SocketClientReqManager.instance.onSocketMsg(obj["protoName"], obj["data"]);
            }
        }
        catch (error) {
            Logger_1.Logger.error("onGameMsg======error==", error);
        }
    }
    sendDataAsync(protoPack) {
        return __awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => {
                this.sendData(protoPack, (data) => {
                    resolve(data);
                });
            });
        });
    }
    sendData(protoPack, callback) {
        let reqData = new SocketRequestData_1.default();
        reqData.id = this.reqId;
        this.reqId++;
        reqData.data = protoPack;
        reqData.callback = callback;
        this.requestMsgQue.push(reqData);
        if (this.isConnected) {
            this.checkSendPack();
        }
        else {
            this.init(this.url, this.id);
        }
    }
    sendProto(protoPack, callback = null) {
        let reqData = new SocketRequestData_1.default();
        reqData.id = this.reqId;
        this.reqId++;
        reqData.data = protoPack;
        reqData.callback = callback;
        this.requestMsgQue.push(reqData);
        if (this.isConnected) {
            this.checkSendPack();
        }
        else {
            this.init(this.url, this.id);
        }
    }
    checkSendPack() {
        if (this.requestMsgQue.length > 0) {
            if (this.isConnected) {
                let socketData = this.requestMsgQue.shift();
                // let serialdata: Uint8Array = this.createSendPack(socketData);
                // let arrayBuffer: ArrayBuffer = serialdata.buffer;
                // this.respCheckMap.set(socketData.id, socketData);
                this.send(this.createSendPack(socketData));
                this.checkSendPack();
            }
        }
    }
    /**
 * 创建发送包
 * @param protoPack
 */
    createSendPack(socketData) {
        let data = {
            "id": socketData.id,
            "data": socketData.data
        };
        this.respCheckMap.set(socketData.id, socketData);
        return JSON.stringify(data);
    }
    // /**
    // * 创建发送包
    // * @param protoPack 
    // */
    // private createSendPack(socketData: SocketRequestData): Uint8Array {
    //     // let protoName: string = ProtoUtils.GetProtoName(socketData.data);
    //     // let protoType: number = ProtoConfig.getProtoRequestType(protoName);
    //     // let serialdata: Uint8Array = socketData.data.serializeBinary();
    //     // let totalPack = ProtoUtils.Create(ProtoConfig.PB_MESSAGE);
    //     // totalPack.setSeq(socketData.id);
    //     // totalPack.setHead(protoType);
    //     // totalPack.setData(serialdata);
    //     // Logger.log("createSendPack==", socketData);
    //     // return totalPack.serializeBinary();
    //     return
    // }
    send(data) {
        if (this.isConnected) {
            this.ws.send(data);
        }
    }
    close() {
        if (this.isConnected) {
            Logger_1.Logger.log("WebSocketClient.close");
            this.ws.close();
        }
    }
    destroy() {
        if (!this.isDestroy) {
            this.isConnecting = false;
            this.isConnected = false;
            this.isDestroy = true;
            WebSocketClientManager_1.WebSocketClientManager.instance.destoyWebSocketClient(this);
            this.account = null;
            this.ws.removeAllListeners();
            this.ws = null;
            this.respCheckMap.clear();
            this.respCheckMap = null;
            this.requestMsgQue = null;
        }
    }
}
exports.WebSocketClient = WebSocketClient;
WebSocketClient.count = 0;
